package exttable;

import utils.Localisation;

import javax.swing.*;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

/**
 * @author Elie Levy Jan 04, 2009
 * GPL License (http://www.gnu.org/copyleft/gpl.html)
 */
public class FreezableTableHeader extends JTableHeader {

	private FreezableActionListener mouseListener;
	private Point point;
	private JMenuItem menuItem;
	private JPopupMenu popupMenu;
	private final String FREEZE_COLUMN = Localisation.getMessage("timetable.freez");
	private final String UNFREEZE_COLUMN = Localisation.getMessage("timetable.unfreez");

	public FreezableTableHeader(JTable table, JScrollPane scrollPane) {
		super(table.getTableHeader().getColumnModel());
		mouseListener = new FreezableActionListener(table, scrollPane);
		table.setTableHeader(this);
		table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		popupMenu = new JPopupMenu();
		menuItem = new JMenuItem(FREEZE_COLUMN);
		menuItem.addActionListener(mouseListener);
		popupMenu.add(menuItem);
		table.addMouseListener(new PopupListener());
		table.setFillsViewportHeight(true);
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		int division = mouseListener.getDivision();
		if (division > 0) {
			Rectangle r = getVisibleRect();
			BufferedImage image = new BufferedImage(division, r.height, BufferedImage.TYPE_INT_ARGB);
			Graphics g2 = image.getGraphics();
			g2.setClip(0, 0, division, r.height);
			g2.setColor(Color.WHITE);
			g2.fillRect(0, 0, division, r.height);
			super.paint(g2);
			g.drawImage(image, r.x, r.y, division, r.height, null);
			g2.dispose();
		}
	}
	private class PopupListener extends MouseAdapter {
		public void mousePressed(MouseEvent e) {
			showPopup(e);
		}

		public void mouseReleased(MouseEvent e) {
			showPopup(e);
		}

		private void showPopup(MouseEvent e) {
			if (e.isPopupTrigger()) {
				point = e.getPoint();
				popupMenu.show(e.getComponent(), e.getX(), e.getY());
			}
		}
	}
	private class FreezableActionListener implements ActionListener {
		private int division;

		private JScrollPane scrollPane;

		private JTable table;

		private boolean added;

		private int col = -1;

		public FreezableActionListener(JTable table, JScrollPane scrollPane) {
			this.table = table;
			this.scrollPane = scrollPane;
		}

		private JLabel frozenColumns = new JLabel() {
			@Override
			public void paintComponent(Graphics g) {
				Rectangle r = table.getBounds();
				if (division > 0) {
					table.invalidate();
					table.validate();
					Rectangle visibleRect = table.getVisibleRect();
					BufferedImage image = new BufferedImage(division, r.height, BufferedImage.TYPE_INT_ARGB);
					Graphics g2 = image.getGraphics();
					g2.setClip(0, visibleRect.y, division, table.getBounds().height);
					g2.setColor(Color.WHITE);
					g2.fillRect(0, 0, division, table.getBounds().height);
					table.paint(g2);
					g.drawImage(image, 0, 0, division, table.getBounds().height, 0, visibleRect.y, division, visibleRect.y + table.getBounds().height, null);
					g.setColor(Color.BLACK);
					for (int i = 0; i < visibleRect.y + table.getBounds().height; i += 8) {
						g.drawLine(division - 1, i, division - 1, i + 4);
						g.drawLine(division - 2, i, division - 2, i + 4);
					}
					g2.dispose();
				}
			}
		};

		public int getDivision() {
			return division;
		}

		public void freeze(Point p) {
			col = table.columnAtPoint(p);
			JLayeredPane pane = table.getRootPane().getLayeredPane();
			if (added) {
				pane.remove(frozenColumns);
			} else {
				scrollPane.addComponentListener(new ComponentListener() {

					public void componentHidden(ComponentEvent arg0) {
						// TODO Auto-generated method stub

					}

					public void componentMoved(ComponentEvent arg0) {
						// TODO Auto-generated method stub

					}

					public void componentResized(ComponentEvent arg0) {
						setBoundsOnFrozenColumns();

					}

					public void componentShown(ComponentEvent arg0) {
						// TODO Auto-generated method stub

					}

				});
			}
			pane.add(frozenColumns, JLayeredPane.POPUP_LAYER);
			setBoundsOnFrozenColumns();
			added = true;
			frozenColumns.setVisible(true);
		}

		public void setBoundsOnFrozenColumns() {
			if (col >= 0) {
				division = table.getCellRect(1, col, true).x
						+ table.getCellRect(1, col, true).width;
				int limit = scrollPane.getBounds().width
						- scrollPane.getVerticalScrollBar().getBounds().width
						- 2;
				division = Math.min(division, limit);
				JLayeredPane pane = table.getRootPane().getLayeredPane();
				Point p = scrollPane.getLocationOnScreen();
				SwingUtilities.convertPointFromScreen(p, pane);
				Rectangle scrollPaneBounds = scrollPane.getBounds();
				int headerHeight = table.getTableHeader().getBounds().height + 1;
				int hScrollHeight = (scrollPane.getHorizontalScrollBar().isVisible()) ? scrollPane.getHorizontalScrollBar().getBounds().height : 0;
				frozenColumns.setBounds(p.x + 1, p.y + headerHeight, division, scrollPaneBounds.height - headerHeight - hScrollHeight - 2);
			}
		}

		public void actionPerformed(ActionEvent arg0) {
			if ((division<=0)&&(point !=null)) {
				freeze(point);
				menuItem.setText(UNFREEZE_COLUMN);
			} else {
				frozenColumns.setVisible(false);
				division = -1;
				col = -1;
				menuItem.setText(FREEZE_COLUMN);
			}
		}
	}
}